﻿#include "UrlFactory.h"
#include "TiandituMapProvider.h"
#include "GaoDeMapProvider.h"
#include "BingMapProvider.h"

const char* UrlFactory::kCopernicusElevationProviderKey = u8"Copernicus Elevation";
const char* UrlFactory::kCopernicusElevationProviderNotice = u8"© Airbus Defence and Space GmbH";

UrlFactory::UrlFactory()
{
    // 天地图
    _providersTable["Tianditu Satellite"] = new TiandituImgMapProvider(this); // 卫星图
    _providersTable["Tianditu Road"] = new TiandituCiaMapProvider(this); // 路网标注信息图
    // 高德
    //_providersTable["Amap Satellite"] = new GaoDeSatelliteMapProvider(this);
    //_providersTable["Amap Street"] = new GaoDeStreetMapProvider(this);
    // 必应
    //_providersTable["Bing Road"]      = new BingRoadMapProvider(this);
    _providersTable["Bing Satellite"] = new BingSatelliteMapProvider(this);
    //_providersTable["Bing Hybrid"]    = new BingHybridMapProvider(this);
}

QNetworkRequest UrlFactory::getTileUrl(int id, int x, int y, int zoom, QNetworkAccessManager* networkManager) const
{
    auto provider = getMapProviderFromId(id);
    if (provider) {
        return provider->getTileURL(x, y, zoom, networkManager);
    }

    qDebug() << "getTileURL : map not registered :" << id;
    return QNetworkRequest(QUrl());
}

QNetworkRequest UrlFactory::getTileUrl(const QString& type, int x, int y, int zoom, QNetworkAccessManager* networkManager) const
{
    auto provider = getMapProviderFromType(type);
    if (provider) {
        return provider->getTileURL(x, y, zoom, networkManager);
    }

    qDebug() << "getTileURL : map not registered :" << type;
    return QNetworkRequest(QUrl());
}

QString UrlFactory::getImageFormat(QString type, const QByteArray& image)
{
    auto provider = getMapProviderFromType(type);
    if (provider) {
        return provider->getImageFormat(image);
    }

    qDebug() << "getImageFormat : Map not registered :" << type;
    return "";
}

QString UrlFactory::getImageFormat(int id, const QByteArray& image)
{
    auto provider = getMapProviderFromId(id);
    if (provider) {
        return provider->getImageFormat(image);
    }

    qDebug() << "getImageFormat : Map not registered :" << id;
    return "";
}

quint32 UrlFactory::averageSizeForType(const QString &type)
{
    if (_providersTable.find(type) != _providersTable.end()) {
        return _providersTable[type]->getAverageSize();
    }
    qDebug() << "UrlFactory::averageSizeForType " << type << " Not registered";

    //    case AirmapElevation:
    //        return AVERAGE_AIRMAP_ELEV_SIZE;
    //    default:
    //        break;
    //    }
    return AVERAGE_TILE_SIZE;
}

int UrlFactory::long2tileX(const QString &mapType, double lon, int z)
{
    return _providersTable[mapType]->long2tileX(lon, z);
}

int UrlFactory::lat2tileY(const QString &mapType, double lat, int z)
{
    return _providersTable[mapType]->lat2tileY(lat, z);
}

// Todo : qHash produce a uint bigger than max(int)
// There is still a low probability for this to
// generate similar hash for different types
int UrlFactory::getIdFromType(const QString& type) const
{
    // qhash为uint,转int会超int范围,右移一位缩小一倍
    return (int)(qHash(type) >> 1);
}

QString UrlFactory::getTypeFromId(const int id) const
{
    for (auto it = _providersTable.constBegin(); it != _providersTable.constEnd(); ++it) {
        if ((int)(qHash(it.key()) >> 1) == id) {
            return it.key();
        }
    }
    qDebug() << "getTypeFromId : id not found" << id;
    return QString("");
}

MapProvider* UrlFactory::getMapProviderFromId(int id) const
{
    return getMapProviderFromType(getTypeFromId(id));
}

MapProvider* UrlFactory::getMapProviderFromType(const QString& type) const
{
    if (_providersTable.find(type) != _providersTable.end())
        return _providersTable[type];

    return nullptr;
}

TileSet UrlFactory::getTileCount(int zoom, double topleftLon, double topleftLat, double bottomRightLon, double bottomRightLat, const QString &mapType)
{
    return _providersTable[mapType]->getTileCount(zoom, topleftLon, topleftLat, bottomRightLon, bottomRightLat);
}

/**
 * @brief 是否是高程数据
 * @param mapId
 * @return 如未获取到,则默认返回false
 */
bool UrlFactory::isElevation(int mapId)
{
    auto provider = getMapProviderFromId(mapId);
    if (provider)
        return provider->isElevationProvider();

    return false;
}

// void UrlFactory::registerProvider(QString name, MapProvider *provider)
// {
//     _providersTable[name] = provider;
// }
